package com.zdxlz.fcmp.upms.api.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zdxlz.fcmp.common.core.exception.BizException;
import com.zdxlz.fcmp.upms.api.dto.SystemUserDto;
import com.zdxlz.fcmp.upms.api.dto.SystemUserReqDto;
import com.zdxlz.fcmp.upms.api.entity.SystemRole;
import com.zdxlz.fcmp.upms.api.entity.SystemTenant;
import com.zdxlz.fcmp.upms.api.entity.SystemUser;
import com.zdxlz.fcmp.upms.api.entity.SystemUserRole;
import com.zdxlz.fcmp.upms.api.mapper.SystemRoleMapper;
import com.zdxlz.fcmp.upms.api.mapper.SystemTenantMapper;
import com.zdxlz.fcmp.upms.api.mapper.SystemUserMapper;
import com.zdxlz.fcmp.upms.api.mapper.SystemUserRoleMapper;
import com.zdxlz.fcmp.upms.api.service.ISystemUserService;
import com.zdxlz.fcmp.upms.api.vo.SystemUserVo;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.zdxlz.fcmp.common.core.constant.CommonConstants.USER_ID;
import static com.zdxlz.fcmp.common.core.constant.enums.ResCode.*;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author: aman
 * @since 2025-01-30
 */
@Service
@AllArgsConstructor
public class SystemUserServiceImpl extends ServiceImpl<SystemUserMapper, SystemUser> implements ISystemUserService {

    @Resource
    private SystemRoleMapper systemRoleMapper;

    @Resource
    private SystemTenantMapper systemTenantMapper;

    @Resource
    private SystemUserRoleMapper systemUserRoleMapper;

    /**
     * @description：分页查询系统用户
     * @author：aman
     * @date：2025/2/14 16:26
     */
    @Override
    public IPage<SystemUserVo> queryUserList(Page<SystemUser> page, SystemUserReqDto dto) {
        LambdaQueryWrapper<SystemUser> queryWrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotEmpty(dto)) {
            queryWrapper
                    .eq(SystemUser::getTenantId, dto.tenantId())
                    .like(StrUtil.isNotBlank(dto.mobile()), SystemUser::getMobile, dto.mobile())
                    .like(StrUtil.isNotBlank(dto.username()), SystemUser::getUsername, dto.username())
                    .eq(ObjectUtil.isNotEmpty(dto.status()), SystemUser::getStatus, dto.status());
        }
        Page<SystemUser> systemUserPage = baseMapper.selectPage(page, queryWrapper);

        List<SystemUserVo> ticketInfoVoList = systemUserPage.getRecords().stream().map(this::convertToSystemUserVo).collect(Collectors.toList());
        IPage<SystemUserVo> userVoIPage = new Page<>(systemUserPage.getCurrent(), systemUserPage.getSize(), systemUserPage.getTotal());
        userVoIPage.setRecords(ticketInfoVoList);
        return userVoIPage;
    }

    /**
     * @description：通过手机号查询用户，判断是否开启验证码
     * @author：aman
     * @date：2025/2/14 16:28
     */
    @Override
    public boolean enableCaptcha(String mobile) {
        LambdaQueryWrapper<SystemUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SystemUser::getMobile, mobile).select(SystemUser::getEnableCaptcha);
        SystemUser user = baseMapper.selectOne(queryWrapper);
        return user != null && user.getEnableCaptcha();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertUser(SystemUserDto dto) {
        try {
            baseMapper.insert(dto);
            long aounctCount = baseMapper.selectCount(new LambdaQueryWrapper<SystemUser>().eq(SystemUser::getTenantId, dto.getTenantId()));
            SystemTenant systemTenant = new SystemTenant();
            systemTenant.setId(dto.getTenantId());
            systemTenant.setAccountCount((int) aounctCount);
            systemTenantMapper.updateById(systemTenant);
        } catch (DataIntegrityViolationException e) {
            throw new DataIntegrityViolationException(ERROR_USER_MOBILE_DISABLED.getReason(), e);
        }
        List<Integer> roleIds = dto.getRoleIds();
        if (CollectionUtil.isNotEmpty(roleIds)) {
            verifyRoleIsExist(roleIds);
            systemUserRoleMapper.insert(buildUserRoleInfo(dto.getId(), roleIds));
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUser(SystemUserDto dto) {
        List<Integer> roleIds = dto.getRoleIds();
        systemUserRoleMapper.deleteByMap(Map.of(USER_ID, dto.getId()));
        if (CollectionUtil.isNotEmpty(roleIds)) {
            verifyRoleIsExist(roleIds);
            systemUserRoleMapper.insert(buildUserRoleInfo(dto.getId(), roleIds));
        }
        try {
            baseMapper.updateById(dto);
        } catch (DataIntegrityViolationException e) {
            throw new DataIntegrityViolationException(ERROR_USER_MOBILE_DISABLED.getReason(), e);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteUser(List<Integer> ids) {
        List<SystemUser> collect = baseMapper.selectByIds(ids).stream().filter(systemUser -> systemUser.getStatus() == Boolean.TRUE).toList();
        if (CollectionUtil.isNotEmpty(collect)) {
            throw new BizException(ERROR_USER_QY_STATUS.getCode(), ERROR_USER_QY_STATUS.getReason());
        }
        List<SystemUserRole> userRoleList = systemUserRoleMapper.selectList(new LambdaQueryWrapper<SystemUserRole>().in(SystemUserRole::getUserId, ids));
        if (CollectionUtil.isNotEmpty(userRoleList)) {
            throw new BizException(ERROR_USER_BANDED_ROLE.getCode(), ERROR_USER_BANDED_ROLE.getReason());
        }
        baseMapper.deleteByIds(ids, true);
        return true;
    }

    /**
     * @description：校验角色是否存在
     * @author：aman
     * @date：2025/2/24 15:06
     */
    public void verifyRoleIsExist(List<Integer> roleIds) {
        List<SystemRole> roleList = systemRoleMapper.selectByIds(roleIds);
        if (roleList.size() != roleIds.size()) throw new BizException(RULE_NOT_EXIST.getCode(), RULE_NOT_EXIST.getReason());
    }

    /**
     * @description：构建用户角色集合信息
     * @author：aman
     * @date：2025/2/24 15:06
     */
    private static List<SystemUserRole> buildUserRoleInfo(Integer userId, List<Integer> roleIds) {
        List<SystemUserRole> systemUserRoles = new ArrayList<>();
        roleIds.forEach(roleId -> {
            SystemUserRole systemUserRole = new SystemUserRole();
            systemUserRole.setUserId(userId);
            systemUserRole.setRoleId(roleId);
            systemUserRoles.add(systemUserRole);
        });
        return systemUserRoles;
    }

    /**
     * @description：系统用户实体装换为系统用户视图
     * @author：aman
     * @date：2025/2/14 16:27
     */
    private SystemUserVo convertToSystemUserVo(SystemUser systemUser) {
        SystemUserVo systemUserVo = new SystemUserVo();
        BeanUtil.copyProperties(systemUser, systemUserVo);
        systemUserVo.setUserType(systemUser.getUserType().getCode());
        List<SystemUserRole> userRoleList = systemUserRoleMapper.selectList(new LambdaQueryWrapper<SystemUserRole>().eq(SystemUserRole::getUserId, systemUser.getId()));
        List<Integer> list = userRoleList.stream().map(SystemUserRole::getRoleId).toList();
        systemUserVo.setRoleIds(list);
        return systemUserVo;
    }
}
